package com.example.ssyinitlearn.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;

import javax.sql.DataSource;

@Configuration
@Order(3)
public class RememberMe_1_Config extends WebSecurityConfigurerAdapter {
    /**
     * 提前用 无加密器 替换掉SSY框架中的默认加密器。这样每次添加新用户时就不必使用 {} 指定加密方式了
     *
     * @return
     */
    @Bean
    PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }

    /**
     * configure 2.1
     * 在 auth覆写方法中写了 UserDetailsService，则此时这个局部 UserDetailsService将会覆盖掉全局的 UserDetailsService
     * 因此此时只能使用 rmbMe-123 来登录 /remember/doLogin1
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();
        // 由于替换掉了默认的加密器，因此不再需要 {123}
        inMemoryUserDetailsManager.createUser(User.builder().username("rmbMe").password("123").roles("user").build());
        auth.userDetailsService(inMemoryUserDetailsManager);
    }

    /**
     * configure 1.1
     * rmbMe的初步使用
     * @param http
     * @throws Exception
     */
//    @Override
//    protected void configure(HttpSecurity http) throws Exception {
//        // 只对 /remember/** 路径的请求进行验证
//        http.antMatcher("/remember/**")
//                .authorizeRequests()
//                .anyRequest().authenticated()
//                .and()
//                // 表单登录配置
//                .formLogin()
//                // 登录页面
//                .loginPage("/rmbMe1.html")
//                // 登录认证处理url
//                .loginProcessingUrl("/remember/doLogin1")
//                .defaultSuccessUrl("/remember/hello")
//                // 登录表单中 username和password的标识
//                .usernameParameter("uname")
//                .passwordParameter("passwd")
//                .permitAll()
//                .and()
//                // 开启 rememberMe配置
//                .rememberMe()
//                // 暂时不知道是干吗用的
//                .key("rmbMe")
//                // 登录表单中 RememberMe的标识
//                .rememberMeParameter("remember-me")
//                .and()
//                .csrf().disable();
//    }

    /**
     * 使用系统的 DataSource创建一个 JdbcTokenRepositoryImpl，直接制作成 Bean
     */
    @Autowired
    DataSource dataSource;
    @Bean
    JdbcTokenRepositoryImpl jdbcTokenRepository(){
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setDataSource(dataSource);
        return jdbcTokenRepository;
    }

    /**
     * configure 1.2
     * 为 rmbMe 添加持久化令牌
     * @param http
     * @throws Exception
     */
//    @Override
//    protected void configure(HttpSecurity http) throws Exception {
//        // 只对 /remember/** 路径的请求进行验证
//        http.antMatcher("/remember/**")
//                .authorizeRequests()
//                .anyRequest().authenticated()
//                .and()
//                // 表单登录配置
//                .formLogin()
//                // 登录页面
//                .loginPage("/rmbMe1.html")
//                // 登录认证处理url
//                .loginProcessingUrl("/remember/doLogin1")
//                .defaultSuccessUrl("/remember/hello")
//                // 登录表单中 username和password的标识
//                .usernameParameter("uname")
//                .passwordParameter("passwd")
//                .permitAll()
//                .and()
//                // 开启 rememberMe配置
//                .rememberMe()
//                // 暂时不知道是干吗用的
//                .key("rmbMe")
//                // 登录表单中 RememberMe的标识
//                .rememberMeParameter("remember-me")
//                .tokenRepository(jdbcTokenRepository())
//                .and()
//                .csrf().disable();
//    }

    /**
     * configure 1.3
     * 二次验证，要求敏感信息必须登录
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 只对 /remember/** 路径的请求进行验证
        http.antMatcher("/remember/**")
                .authorizeRequests()
                // 对 /remember/protected 必须完整认证，不准 rmbMe
                .antMatchers("/remember/protected").fullyAuthenticated()
                .anyRequest().authenticated()
                .and()
                // 表单登录配置
                .formLogin()
                // 登录页面
                .loginPage("/rmbMe1.html")
                // 登录认证处理url
                .loginProcessingUrl("/remember/doLogin1")
                .defaultSuccessUrl("/remember/hello")
                // 登录表单中 username和password的标识
                .usernameParameter("uname")
                .passwordParameter("passwd")
                .permitAll()
                .and()
                // 开启 rememberMe配置
                .rememberMe()
                // 暂时不知道是干吗用的
                .key("rmbMe")
                // 登录表单中 RememberMe的标识
                .rememberMeParameter("remember-me")
                .tokenRepository(jdbcTokenRepository())
                // 添加 rmbMe 过期时间
                .tokenValiditySeconds(60)
                .and()
                .csrf().disable();
    }
}
